import re
from datetime import datetime,timedelta
from typing import List, Tuple, Dict
import lunardate

class LunarHour:
    def __init__(self, HourName="", MinHour=0, MaxHour=0, maxMinute=59):
        self.HourName = HourName
        self.MinHour = MinHour
        self.MaxHour = MaxHour
        self.maxMinute = maxMinute

class NongLiAssistant:
    """农历相关类"""
    
    # 六十甲子
    LiuShiJiaZhi = [
        "甲子", "乙丑", "丙寅", "丁卯", "戊辰", "己巳", "庚午", "辛未", "壬申", "癸酉",
        "甲戌", "乙亥", "丙子", "丁丑", "戊寅", "己卯", "庚辰", "辛巳", "壬午", "癸未",
        "甲申", "乙酉", "丙戌", "丁亥", "戊子", "己丑", "庚寅", "辛卯", "壬辰", "癸巳",
        "甲午", "乙未", "丙申", "丁酉", "戊戌", "己亥", "庚子", "辛丑", "壬寅", "癸卯",
        "甲辰", "乙巳", "丙午", "丁未", "戊申", "己酉", "庚戌", "辛亥", "壬子", "癸丑",
        "甲寅", "乙卯", "丙辰", "丁巳", "戊午", "己未", "庚申", "辛酉", "壬戌", "癸亥"
    ]
    
    TIANGAN = ["癸", "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"]
    DIZHI = ["亥", "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"]
    
    # 日
    DAY = ["", "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", 
           "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", 
           "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"]
    
    DAY2 = ["", "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", 
            "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", 
            "二十一", "二十二", "二十三", "二十四", "二十五", "二十六", "二十七", "二十八", "二十九", "三十"]
    
    # 月份
    Lunar_Month_Arr = ["", "正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"]
    
    # 农历十二时辰
    SHIER_HOUR = [
        LunarHour(HourName="子", MinHour=23, MaxHour=0, maxMinute=59),
        LunarHour(HourName="丑", MinHour=1, MaxHour=2, maxMinute=59),
        LunarHour(HourName="寅", MinHour=3, MaxHour=4, maxMinute=59),
        LunarHour(HourName="卯", MinHour=5, MaxHour=6, maxMinute=59),
        LunarHour(HourName="辰", MinHour=7, MaxHour=8, maxMinute=59),
        LunarHour(HourName="巳", MinHour=9, MaxHour=10, maxMinute=59),
        LunarHour(HourName="午", MinHour=11, MaxHour=12, maxMinute=59),
        LunarHour(HourName="未", MinHour=13, MaxHour=14, maxMinute=59),
        LunarHour(HourName="申", MinHour=15, MaxHour=16, maxMinute=59),
        LunarHour(HourName="酉", MinHour=17, MaxHour=18, maxMinute=59),
        LunarHour(HourName="戌", MinHour=19, MaxHour=20, maxMinute=59),
        LunarHour(HourName="亥", MinHour=21, MaxHour=22, maxMinute=59)
    ]
    
    @staticmethod
    def GongYunToGanZhi(gongYuanYear: int) -> str:
        """公元年转换成干支"""
        mod = (gongYuanYear - 3) % 10
        partOne = NongLiAssistant.TIANGAN[mod]
        
        mod2 = (gongYuanYear - 3) % 12
        partTwo = NongLiAssistant.DIZHI[mod2]
        
        return partOne + partTwo
    
    @staticmethod
    def GetLunarDate(reqtime: str) -> Tuple[str, str, str, str]:
        """
        将当前时间转成农历月日
        :param reqtime: 公历日期
        :return: item1：年，item2：月,itme3：日, itme4：干支年份
        """
        dt = datetime.strptime(reqtime, "%Y-%m-%d")
        lunar = lunardate.LunarDate.fromSolarDate(dt.year, dt.month, dt.day)
    
        year = lunar.year
        month = NongLiAssistant.Lunar_Month_Arr[lunar.month]
        day = NongLiAssistant.DAY[lunar.day]
        ganzhi = NongLiAssistant.LiuShiJiaZhi[(year - 4) % 60]  # 简化计算
        return (str(year), month, day, ganzhi)
    
    @staticmethod
    def GetMonth(time: datetime) -> str:
        """获取农历月份"""
        # 注意：这里需要替换为实际的农历计算库
        # 此处仅保留原逻辑结构
        return "正月"  # 替换为实际农历月
    
    @staticmethod
    def GetNongliNowHour(time: datetime, longitude: float = 120) -> str:
        """获取当地真太阳农历时辰"""
        h = time.hour
        m = time.minute
        
        # 查找匹配的时辰
        for hour_range in NongLiAssistant.SHIER_HOUR:
            min_h = hour_range.MinHour
            max_h = hour_range.MaxHour
            
            # 处理子时特殊情况 (23:00-0:59)
            if hour_range.HourName == "子":
                if (h == 23 and m <= 59) or (h == 0 and m <= 59):
                    return "子"
            # 其他时辰
            elif min_h <= h <= max_h and m <= hour_range.maxMinute:
                return hour_range.HourName
        
        # 默认返回子时
        return "子"
    
    @staticmethod
    def GetDaysNumberInMonth_Lunar(year: int, month: int) -> int:
        """获取农历月份天数"""
        # 注意：这里需要替换为实际的农历计算库
        return 30  # 替换为实际天数
    
    @staticmethod
    def GetStandNongLiMonth(month: str) -> str:
        """标准农历月份"""
        if month == "正月":
            return "一月"
        elif month == "冬月":
            return "十一月"
        elif month == "腊月":
            return "十二月"
        elif re.search(r"\d{1,}", month):
            month_map = {
                1: "一月", 2: "二月", 3: "三月", 4: "四月", 5: "五月", 6: "六月",
                7: "七月", 8: "八月", 9: "九月", 10: "十月", 11: "十一月", 12: "十二月"
            }
            try:
                month_num = int(re.search(r"\d+", month).group())
                return month_map.get(month_num, month)
            except:
                return month
        else:
            return month
    
    @staticmethod
    def GetStandNongLiDay(day: str) -> str:
        """标准农历日期"""
        if "廿" in day:
            return day.replace("廿", "二十")
        elif "初" in day:
            return day.replace("初", "")
        elif "卅" in day:
            return day.replace("卅", "三十")
        elif re.search(r"\d{1,}", day):
            # 需要导入CommonVarRule
            # from ZiWeiPaiPan.EntiyModel import CommonVarRule
            day_num = int(re.search(r"\d+", day).group())
            # 伪代码 - 实际需要CommonVarRule
            day_map = {
                1: "一", 2: "二", 3: "三", 4: "四", 5: "五", 6: "六", 7: "七", 8: "八", 9: "九", 10: "十",
                11: "十一", 12: "十二", 13: "十三", 14: "十四", 15: "十五", 16: "十六", 17: "十七", 18: "十八", 19: "十九", 20: "二十",
                21: "二十一", 22: "二十二", 23: "二十三", 24: "二十四", 25: "二十五", 26: "二十六", 27: "二十七", 28: "二十八", 29: "二十九", 30: "三十"
            }
            return day_map.get(day_num, day)
        else:
            return day
    
    @staticmethod
    def GetSunTimeByLongitude(beiJinTime: datetime, longitude: float) -> datetime:
        """北京时间转成真太阳时"""
        addMinute = int((longitude - 120) * (60 / 15))
        return beiJinTime + timedelta(minutes=addMinute)
    
    @staticmethod
    def GetTimeToNLHour(time_str: str) -> str:
        """公历时间转成农历时辰 (例:8:30)"""
        try:
            time_parts = time_str.split(':')
            hour = int(time_parts[0])
            
            if 23 <= hour or hour < 1:
                return "子"
            elif 1 <= hour < 3:
                return "丑"
            elif 3 <= hour < 5:
                return "寅"
            elif 5 <= hour < 7:
                return "卯"
            elif 7 <= hour < 9:
                return "辰"
            elif 9 <= hour < 11:
                return "巳"
            elif 11 <= hour < 13:
                return "午"
            elif 13 <= hour < 15:
                return "未"
            elif 15 <= hour < 17:
                return "申"
            elif 17 <= hour < 19:
                return "酉"
            elif 19 <= hour < 21:
                return "戌"
            elif 21 <= hour < 23:
                return "亥"
        except:
            pass
        return "子"
    
    @staticmethod
    def LunarHourTo(lHour: str) -> Tuple[int, int]:
        """农历时辰转成公历，item1：最小值，item2：最大值"""
        for hour_range in NongLiAssistant.SHIER_HOUR:
            if hour_range.HourName == lHour:
                return (hour_range.MinHour, hour_range.MaxHour)
        return (0, 0)  # 默认值
    

if __name__ == "__main__":
    # 测试代码
    print(NongLiAssistant.GetLunarDate("2025-07-08"))